package utils

import (
	"github.com/gin-gonic/gin"
	"go-backend-simple-scaffold/common/req"
	"go-backend-simple-scaffold/global"
	"go-backend-simple-scaffold/model/entity"
	"net"
	"time"
)

// 清空cookie 中的 token
func ClearToken(c *gin.Context) {
	// 增加cookie x-token 向来源的web添加
	host, _, err := net.SplitHostPort(c.Request.Host)
	if err != nil {
		host = c.Request.Host
	}
	if net.ParseIP(host) != nil {
		c.SetCookie("x-token", "", -1, "/", "", false, false)
	} else {
		c.SetCookie("x-token", "", -1, "/", host, false, false)
	}
}

func SetToken(c *gin.Context, token string, maxAge int) {
	// 增加cookie x-token 向来源的web添加
	host, _, err := net.SplitHostPort(c.Request.Host)
	if err != nil {
		host = c.Request.Host
	}
	if net.ParseIP(host) != nil {
		c.SetCookie("x-token", token, maxAge, "/", "", false, false)
	} else {
		c.SetCookie("x-token", token, maxAge, "/", host, false, false)
	}
}

func GetToken(c *gin.Context) string {
	// 从cookie中获取token
	token, _ := c.Cookie("x-token")
	if token == "" {
		// 创建jwt对象
		j := NewJWT()
		// 从请求头中获取token
		token = c.Request.Header.Get("x-token")
		// 解析token
		claims, err := j.ParseToken(token)
		if err != nil {
			global.GBSS_LOG.Error("重新写入cookie token失败，未能成功解析token，请检查请求头是否存在x-token且claims是否为规定的结构体")
			return token
		}
		SetToken(c, token, int((claims.ExpiresAt.Unix()-time.Now().Unix())/60))
	}
	return token
}

func GetClaims(c *gin.Context) (*req.CustomClaims, error) {
	token := GetToken(c)
	j := NewJWT()
	claims, err := j.ParseToken(token)
	if err != nil {
		global.GBSS_LOG.Error("从Gin的Context中获取的 jwt token 解析信息失败，请检查请求头是否存在x-token且claims是否为规定结构")
	}
	return claims, err
}

// GetUserID 从Gin的Context中获取从jwt解析出来的用户ID
func GetUserID(c *gin.Context) string {
	// 判断gin.Context中是否有claims，如果没有就从cookie或者header中获取
	if claims, exists := c.Get("claims"); !exists {
		if cl, err := GetClaims(c); err != nil {
			return ""
		} else {
			return cl.BaseClaims.Id
		}
	} else {
		waitUse := claims.(*req.CustomClaims)
		return waitUse.BaseClaims.Id
	}
}

// GetUserAuthorityId 从 gin 的 Context 中获取从 jwt 解析出来的用户角色Id
func GetUserAuthorityId(c *gin.Context) string {
	if claims, exists := c.Get("claims"); !exists {
		if cl, err := GetClaims(c); err != nil {
			return ""
		} else {
			return cl.AuthorityId
		}
	} else {
		waitUse := claims.(*req.CustomClaims)
		return waitUse.AuthorityId
	}
}

func GetUserInfo(c *gin.Context) *req.CustomClaims {
	if claims, exists := c.Get("claims"); !exists {
		if cl, err := GetClaims(c); err != nil {
			return nil
		} else {
			return cl
		}
	} else {
		waitUse := claims.(*req.CustomClaims)
		return waitUse
	}
}

func GetUserName(c *gin.Context) string {
	if claims, exists := c.Get("claims"); !exists {
		if cl, err := GetClaims(c); err != nil {
			return ""
		} else {
			return cl.UserName
		}
	} else {
		waitUse := claims.(*req.CustomClaims)
		return waitUse.UserName
	}
}

func LoginToken(user entity.GbssUser) (token string, claims req.CustomClaims, err error) {
	j := &JWT{
		SigningKey: []byte(global.GBSS_CONFIG.JWT.SigningKey),
	}
	claims = j.CreateClaims(req.BaseClaims{
		Id:          user.ID,
		NickName:    user.NickName,
		UserName:    user.UserName,
		AuthorityId: user.AuthorityId,
	})
	token, err = j.CreateToken(claims)
	return
}
